﻿/*
------------------------------------------------------------------------------
This source file is a part of The Two-Layered GUI Toolkit.

Copyright (c) 2011 Florian Haag

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
------------------------------------------------------------------------------
 */
using System;
using System.Collections.Generic;

using TwoLayeredGUI.Wizard;
using TwoLayeredGUI.ValueInput;

namespace TwoLayeredGUI.Samples.SampleCore
{
	partial class Example
	{
		public class Person
		{
			private string givenName;
			
			public string GivenName {
				get {
					return givenName;
				}
				set {
					givenName = value;
				}
			}
			
			private string surname;
			
			public string Surname {
				get {
					return surname;
				}
				set {
					surname = value;
				}
			}
			
			private int age;
			
			public int Age {
				get {
					return age;
				}
				set {
					age = value;
				}
			}
			
			private string eMail;
			
			public string EMail {
				get {
					return eMail;
				}
				set {
					eMail = value;
				}
			}
			
			public override string ToString()
			{
				return string.Format("{0} {1} ({2}): {3}",
				                     givenName,
				                     surname,
				                     age,
				                     string.IsNullOrEmpty(eMail) ? "?" : eMail);
			}
		}
		
		public static Wizard<string> GetHelloWorldWizard()
		{
			var result = new Wizard<string>();
			result.Pages.AddTextPage("Hello World!", "Welcome to the wizard framework of the Two-Layered GUI Toolkit! This example wizard demonstrates what a simple wizard with a few pages can look like.\n\nCheck out the other sample wizards and the source code, too, to get an idea of what this wizard framework can do.");
			result.Pages.AddTextPage("Now let us go on.", "This is the second page of this wonderfully small example wizard.", true);
			return result;
		}
		
		public static Wizard<Person> GetPersonWizard()
		{
			return GetPersonWizard(true);
		}
		
		private static Wizard<Person> GetPersonWizard(bool standalone)
		{
			var result = new Wizard<Person>();
			
			if (standalone) {
				result.Pages.AddTextPage("Describe a Person", "In this wizard, you can input the attributes of a person record. Click Next to continue.");
			}
			result.Pages.Add(new ValueInputPage<Person>("Basic Data", "Input some basic information about the person to describe, please.",
			                                            (ctl, vals) => {
			                                            	vals[0] = ctl.Settings.GivenName;
			                                            	vals[1] = ctl.Settings.Surname;
			                                            	vals[2] = ctl.Settings.Age;
			                                            },
			                                            (ctl, vals) => {
			                                            	ctl.Settings.GivenName = (vals[0] as string) ?? "";
			                                            	ctl.Settings.Surname = (vals[1] as string) ?? "";
			                                            	ctl.Settings.Age = (int)vals[2];
			                                            },
			                                            new StringValue(new AccessString("First name:")),
			                                            new StringValue(new AccessString("Last name:")),
			                                            new Int32Value(new AccessString("Age:")) {
			                                            	MinValue = 0,
			                                            	MaxValue = 200
			                                            }));
			result.Pages.Add(new ValueInputPage<Person>("E-Mail", "Please enter the e-mail address of the person. Note that not all e-mail addresses are accepted.",
			                                            (ctl, vals) => {
			                                            	vals[0] = ctl.Settings.EMail;
			                                            },
			                                            (ctl, vals) => {
			                                            	ctl.Settings.EMail = (vals[0] as string) ?? "";
			                                            },
			                                            new StringValue(new AccessString("E-Mail:"), new ValueInput.Validators.RegexStringValidator("^[a-z]+(\\.[a-z]+)?\\@[a-z]+\\.[a-z]+$"))) {
			                 	TopDesc = "Note that you have to enter a valid e-mail addres in order to proceed.",
			                 	BottomDesc = "Once you have input an e-mail address, click the \"Next\" button."
			                 });
			if (standalone) {
				result.Pages.AddTextPage("Done", "Thank you. You have just described a person.", true);
			}
			
			return result;
		}
		
		private static Wizard<IndexedSettings<int, IList<Person>>> GetPersonInListWizard()
		{
			var result = new Wizard<IndexedSettings<int, IList<Person>>>();
			
			result.NextWizards.Add(personInList => personInList.Settings[personInList.Index], GetPersonWizard(false));
			
			var continuePage =
				new ChoicePage<IndexedSettings<int, IList<Person>>>("Add Another Contact", "Select whether you would like to add another contact to the list.",
				                                                    controller => controller.Settings.Index + 1 < controller.Settings.Settings.Count ? 0 : 1,
				                                                    delegate(IWizardController<IndexedSettings<int, IList<Person>>> controller, int choice) {
				                                                    	var settings = controller.Settings;
				                                                    	if (choice == 0) {
				                                                    		while (settings.Index + 1 >= settings.Settings.Count) {
				                                                    			settings.Settings.Add(new Person());
				                                                    		}
				                                                    	} else {
				                                                    		while (settings.Index + 1 < settings.Settings.Count) {
				                                                    			settings.Settings.RemoveAt(settings.Settings.Count - 1);
				                                                    		}
				                                                    	}
				                                                    }, new BooleanValue(new AccessString("Yes")), new BooleanValue(new AccessString("No")));
			continuePage.ChoiceChanged += delegate(object sender, WizardChoiceEventArgs<IndexedSettings<int, IList<Person>>> e) {
				var page = e.Controller.Page as ChoicePage<IndexedSettings<int, IList<Person>>>;
				if (page != null) {
					var settings = e.Controller.Settings;
					if (e.Choice == 0) {
	      		if (e.Controller.Wizard.NextWizards.Count <= 0) {
	      			e.Controller.Wizard.NextWizards.Add(item => new IndexedSettings<int, IList<Person>>(item.Index + 1, item.Settings),
							                                    GetPersonInListWizard());
	      		}
					} else {
	      		e.Controller.Wizard.NextWizards.Clear();
					}
					e.Controller.UpdateButtonStates();
				}
			};
			continuePage.TopDesc = "Would you like to add another person?";
			result.NextWizards.Add(continuePage);
			
			return result;
		}
		
		public static Wizard<IList<Person>> GetPersonListWizard()
		{
			var result = new Wizard<IList<Person>>();
			
			result.Pages.AddTextPage("Person List", "This wizard allows you to assemble a list of persons.");
			result.NextWizards.Add(list => {
			                       	if (list.Count <= 0) {
			                       		list.Add(new Person());
			                       	}
			                       	return new IndexedSettings<int, IList<Person>>(0, list);
			                       },
			                       GetPersonInListWizard());
			result.NextWizards.Add(new SummaryPage<IList<Person>>("List Entered", "Please check whether the entered information is correct.",
			                                                      ctl => {
			                                                      	var sb = new System.Text.StringBuilder();
			                                                      	foreach (var person in ctl.Settings) {
			                                                      		sb.AppendLine(person.ToString());
			                                                      	}
			                                                      	sb.AppendFormat("{0} person(s) described.", ctl.Settings.Count);
			                                                      	return sb.ToString();
			                                                      }),
			                       new TextPage<IList<Person>>("Thank you!", "You have just entered a list of persons.") {
			                       	AllowFinish = true
			                       });
			
			return result;
		}
		
		private static void DoWizardWork(IProgressIndicatorController progressController, object settings)
		{
			for (int i = 0; i <= 100; i++) {
				System.Threading.Thread.Sleep(100);
				progressController.AddDetail(i.ToString());
				progressController.Progress = i;
				if (i % 20 == 0) {
					progressController.StatusMessage = ">= " + i.ToString() + " :-)";
					if (progressController.IsCanceled) {
						return;
					}
				}
			}
			System.Threading.Thread.Sleep(100);
			//controller.AllowNext = true;
		}
		
		public static Wizard<object> GetWorkingWizard()
		{
			var result = new Wizard<object>();
			
			result.Pages.AddTextPage("Working Wizard", "This wizard demonstrates how to display the progress of a longer operation.");
			
			result.Pages.Add(new ProgressPage<object>("Work in Progress", "Please wait until the work has been completed. This may take a few moments.", DoWizardWork) {
			                 	ShowDetails = true
			                 });
			
			result.Pages.AddTextPage("The End", "This is the end of the wizard.", true);
			
			return result;
		}
	}
}
